#include <PortableDeviceApi.h>
#include <PortableDevice.h>    
#include "atlbase.h"
#include "WPDeviceManager.h"
#include "WPDException.h"
#include <vcclr.h>
//C:\WMSDK\WMFSDK95\WMDM\inc
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;

WPDeviceManager::WPDeviceManager()
{
}

WPDeviceManager::~WPDeviceManager()
{
}


WPDevice^ WPDeviceManager::createWPDDevice(String^ deviceID)
{
	WPDevice ^device = gcnew WPDevice();
	device->DeviceFriendlyName = getDeviceFriednlyName(deviceID);
	device->DeviceDescription = getDeviceDescription(deviceID);
	device->DeviceManufacturer = getDeviceManufacturer(deviceID);
	device->DeviceID = deviceID;
	return device;
}


List<WPDevice^>^ WPDeviceManager::enumerateDevices()
{
	HRESULT                         hr            = S_OK;
	DWORD                           cPnPDeviceIDs = 0;
	LPWSTR*                         pPnpDeviceIDs = NULL;
	CComPtr<IPortableDeviceManager> pPortableDeviceManager;
	void *tmp = (void *)&WPD_OBJECT_PARENT_ID;
	// CoCreate the IPortableDeviceManager interface to enumerate
	// portable devices and to get information about them.
	hr = CoCreateInstance(CLSID_PortableDeviceManager,
						  NULL,
						  CLSCTX_INPROC_SERVER,
						  IID_IPortableDeviceManager,
						  (VOID**) &pPortableDeviceManager);

	if (FAILED(hr))
	{
		//printf("! Failed to CoCreateInstance CLSID_PortableDeviceManager, hr = 0x%lx\n",hr);
		throw gcnew WPDException(L"Failed to CoCreateInstance CLSID_PortableDeviceManager, hr = "+hr);
	}

	m_pPortableDeviceManager = (void *)pPortableDeviceManager;
	// First, pass NULL as the LPWSTR array pointer to get the total number
	// of devices found on the system.
	if (SUCCEEDED(hr))
	{
		hr = pPortableDeviceManager->GetDevices(NULL, &cPnPDeviceIDs);
		if (FAILED(hr))
		{
			throw gcnew WPDException(L"Failed to get number of devices on the system, hr = "+hr);
			//printf("! Failed to get number of devices on the system, hr = 0x%lx\n",hr);
		}
	}

	// Report the number of devices found.  NOTE: we will report 0, if an error
	// occured.

	//printf("\n%d Windows Portable Device(s) found on the system\n\n", cPnPDeviceIDs);

	// Second, allocate an array to hold the PnPDeviceID strings returned from
	// the IPortableDeviceManager::GetDevices method
	List<WPDevice^>^ devicesList = gcnew List<WPDevice^>();

	if (SUCCEEDED(hr) && (cPnPDeviceIDs > 0))
	{
		pPnpDeviceIDs = new LPWSTR[cPnPDeviceIDs];
		if (pPnpDeviceIDs != NULL)
		{
			DWORD dwIndex = 0;

			hr = pPortableDeviceManager->GetDevices(pPnpDeviceIDs, &cPnPDeviceIDs);
			if (SUCCEEDED(hr))
			{
				for (dwIndex = 0; dwIndex < cPnPDeviceIDs; dwIndex++)
				{
					WPDevice^ device =  createWPDDevice(gcnew String(pPnpDeviceIDs[dwIndex]));
					devicesList->Add(device);
				}
			}
			else
			{
				//printf("! Failed to get the device list from the system, hr = 0x%lx\n",hr);
			}

			// Free all returned PnPDeviceID strings by using CoTaskMemFree.
			// NOTE: CoTaskMemFree can handle NULL pointers, so no NULL
			//       check is needed.
			for (dwIndex = 0; dwIndex < cPnPDeviceIDs; dwIndex++)
			{
				CoTaskMemFree(pPnpDeviceIDs[dwIndex]);
				pPnpDeviceIDs[dwIndex] = NULL;
			}

			// Delete the array of LPWSTR pointers
			delete [] pPnpDeviceIDs;
			pPnpDeviceIDs = NULL;
		}
		else
		{
			//printf("! Failed to allocate memory for LPWSTR array\n");
		}
	}

	return devicesList;
}

// Reads and displays the device friendly name for the specified PnPDeviceID string
String ^WPDeviceManager::getDeviceFriednlyName(String^ deviceID)
{
	HRESULT hr              = S_OK;
	DWORD   cchFriendlyName = 0;
	LPWSTR  wszFriendlyName = NULL;
	String^ tmpString;

	// Validate input parameters
	if (m_pPortableDeviceManager == NULL)
	{
	}

	if (String::IsNullOrEmpty(deviceID))
	{
	}

	pin_ptr<const __wchar_t> umstring = PtrToStringChars(deviceID);


	IPortableDeviceManager* pPortableDeviceManager = ((IPortableDeviceManager*)m_pPortableDeviceManager);
	hr = pPortableDeviceManager->GetDeviceFriendlyName(umstring, NULL, &cchFriendlyName);
	if (SUCCEEDED(hr))
	{
		if ((hr == S_OK) && (cchFriendlyName > 0))
		{
			wszFriendlyName = new WCHAR[cchFriendlyName];
			if (wszFriendlyName != NULL)
			{
				hr = pPortableDeviceManager->GetDeviceFriendlyName(umstring, wszFriendlyName, &cchFriendlyName);
				
				if (SUCCEEDED(hr))
				{
					tmpString = gcnew String(wszFriendlyName);
				}
				else
				{
					//printf("! Failed to get device friendly name, hr = 0x%lx\n",hr);
				}

				// Delete the allocated friendly name string
				delete [] wszFriendlyName;
				wszFriendlyName = NULL;
			}
			else
			{
				//printf("! Failed to allocate memory for the device friendly name string\n");
			}
		}

		if (SUCCEEDED(hr) && (cchFriendlyName == 0))
		{
			//printf("The device did not provide a friendly name.\n");
		}

	} else 
	{
		//printf("! Failed to get number of characters for device friendly name, hr = 0x%lx\n",hr);
	}

	return tmpString;
}



// Reads and displays the device manufacturer for the specified PnPDeviceID string
String ^WPDeviceManager::getDeviceManufacturer(String^ deviceID)
{
	HRESULT hr              = S_OK;
	DWORD   cchManufacturer = 0;
	LPWSTR  wszManufacturer = NULL;
	String^ tmpString;
	// Validate input parameters
	if (m_pPortableDeviceManager == NULL)
	{
	}

	if (String::IsNullOrEmpty(deviceID))
	{
	}

	pin_ptr<const __wchar_t> umstring = PtrToStringChars(deviceID);

	IPortableDeviceManager* pPortableDeviceManager = ((IPortableDeviceManager*)m_pPortableDeviceManager);
	// First, pass NULL as the LPWSTR return string parameter to get the total number
	// of characters to allocate for the string value.


	hr = pPortableDeviceManager->GetDeviceManufacturer(umstring, NULL, &cchManufacturer);
	if (SUCCEEDED(hr))
	{
		// Second allocate the number of characters needed and retrieve the string value.
		if ((hr == S_OK) && (cchManufacturer > 0))
		{
			wszManufacturer = new WCHAR[cchManufacturer];
			if (wszManufacturer != NULL)
			{
				hr = pPortableDeviceManager->GetDeviceManufacturer(umstring, wszManufacturer, &cchManufacturer);
				if (SUCCEEDED(hr))
				{
					tmpString = gcnew String(wszManufacturer);
				}
				else
				{
					//printf("! Failed to get device friendly name, hr = 0x%lx\n",hr);
				}

				// Delete the allocated friendly name string
				delete [] wszManufacturer;
				wszManufacturer = NULL;
			}
			else
			{
				//printf("! Failed to allocate memory for the device friendly name string\n");
			}
		}

		if (SUCCEEDED(hr) && (cchManufacturer == 0))
		{
			//printf("The device did not provide a friendly name.\n");
		}

	} else 
	{
		//printf("! Failed to get number of characters for device friendly name, hr = 0x%lx\n",hr);
	}

	return tmpString;
}



// Reads and displays the device discription for the specified PnPDeviceID string
String ^WPDeviceManager::getDeviceDescription(String^ deviceID)
{
	HRESULT hr              = S_OK;
	DWORD   cchDescription = 0;
	LPWSTR  wszDescription = NULL;
	String ^tmpString;
	// Validate input parameters
	if (m_pPortableDeviceManager == NULL)
	{
		//printf("! A NULL IPortableDeviceManager interface pointer was received\n");
		//return NULL;
	}

	if (String::IsNullOrEmpty(deviceID))
	{
		//printf("! A NULL PnPDeviceID string pointer was received\n");
		//return NULL;
	}

	pin_ptr<const __wchar_t> umstring = PtrToStringChars(deviceID);

	IPortableDeviceManager* pPortableDeviceManager = ((IPortableDeviceManager*)m_pPortableDeviceManager);
	// First, pass NULL as the LPWSTR return string parameter to get the total number
	// of characters to allocate for the string value.


	hr = pPortableDeviceManager->GetDeviceDescription(umstring, NULL, &cchDescription);
	if (SUCCEEDED(hr))
	{
		// Second allocate the number of characters needed and retrieve the string value.
		if ((hr == S_OK) && (cchDescription > 0))
		{
			wszDescription = new WCHAR[cchDescription];
			if (wszDescription != NULL)
			{
				hr = pPortableDeviceManager->GetDeviceDescription(umstring, wszDescription, &cchDescription);
				if (SUCCEEDED(hr))
				{
					tmpString = gcnew String(wszDescription);
				}
				else
				{
					//printf("! Failed to get device friendly name, hr = 0x%lx\n",hr);
				}

				// Delete the allocated friendly name string
				delete [] wszDescription;
				wszDescription = NULL;
			}
			else
			{
				//printf("! Failed to allocate memory for the device friendly name string\n");
			}
		}

		if (SUCCEEDED(hr) && (cchDescription == 0))
		{
			//printf("The device did not provide a friendly name.\n");
		}

	} else 
	{
		//printf("! Failed to get number of characters for device friendly name, hr = 0x%lx\n",hr);
	}

	return tmpString;
}







